package com.ymttest.utils.compare;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;

import org.json.JSONObject;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class CompareHelper {
	private LoggerInterface logger;
	private List<Runnable> runList = new ArrayList<>();
	private CompareThreadPool compareThreadPool;

	private <T> T getBeanFromJson(JSONObject jsonObject, Class<T> clz, String dateFormat) {
		if (dateFormat == null || dateFormat.equals("")) {
			Gson gson = new GsonBuilder().create();
			return gson.fromJson(jsonObject.toString(), clz);
		} else {
			Gson gson = new GsonBuilder().setDateFormat(dateFormat).create();
			return gson.fromJson(jsonObject.toString(), clz);
		}

	}

	public CompareHelper(LoggerInterface logger, int threadNum) {
		this.logger = logger;
		AssertHelper.setLoggerInterface(logger);
		compareThreadPool = new CompareThreadPool(threadNum);
	}
	
	
	public CompareHelper() {
		LogPathConf logPathConf = new LogPathConf(true);
		LoggerInterface logger = new LoggerHelper(logPathConf);
		this.logger = logger;
		AssertHelper.setLoggerInterface(logger);
		compareThreadPool = new CompareThreadPool(5);
	}
	

	public <T> void setCompareApiData(CallAPI oldApi, CallAPI newApi, List<Map<String, Object>> paramMapList,
			Class<T> clz) {
		setCompareApiData(oldApi, null, newApi, null, paramMapList, clz);
	}

	public <T> void setCompareApiData(CallAPI oldApi, String oldTimeFormat, CallAPI newApi, String newTimeFormat,
			List<Map<String, Object>> paramMapList, Class<T> clz) {
		setCompareApiData(oldApi, oldTimeFormat, newApi, newTimeFormat, paramMapList, clz, null);
	}

/*	public <T> void setCompareApiData(CallAPI oldApi, String oldTimeFormat, CallAPI newApi, String newTimeFormat,
			List<Map<String, Object>> paramMapList, Class<T> clz, BiFunction<JSONObject, T, T> function) {
		runList.addAll(TaskFactory.generateTasks(paramMapList, x -> {
			JSONObject oldRet = oldApi.callAndReturn(x);
			JSONObject newRet = newApi.callAndReturn(x);

			String desc = "ApiName: " + oldApi.getApiName() + ", Param:" + x.toString();

			try {
				JSONObject oldData = oldRet.getJSONObject("Data");
				JSONObject newData = newRet.getJSONObject("Data");

				T oldBean = getBeanFromJson(oldData, clz, oldTimeFormat);
				if (function != null) {
					oldBean = function.apply(oldData, oldBean);
				}

				T newBean = getBeanFromJson(newData, clz, newTimeFormat);

				AssertHelper.assertResultEqual(oldBean, newBean, desc);
			} catch (Exception e) {
				logger.failure(desc);
			}
		}));
	}*/



	public <T,V extends CallAPI> void setCompareApiData(V oldApi, String oldTimeFormat,
														V newApi, String newTimeFormat,
														List<Map<String, Object>> paramMapList,
														Class<T> clz, 
														BiFunction<JSONObject, T, T> beanHandlefunction) {
		
		runList.addAll(TaskFactory.generateTasks(paramMapList, x -> {

			String desc = "ApiName: " + oldApi.getApiName() + ", Param:" + x.toString();
			System.out.println(desc);
			try {
				JSONObject oldRet = oldApi.getClass().newInstance().callAndReturn(x);
				JSONObject newRet = newApi.getClass().newInstance().callAndReturn(x);
				
				
				if (oldRet.isNull("Data")&&newRet.isNull("Data")){
					logger.verifyEquals(true, true, desc+",new return and old return are all null");
					return;
				}else if (!oldRet.isNull("Data")&&newRet.isNull("Data")){
					logger.failure(desc+",new return is null and old is not null");
					return;
				}else if (oldRet.isNull("Data")&&!newRet.isNull("Data")){
					logger.failure(desc+",old return is null and new is not null");
					return;
				}
				
				JSONObject oldData = oldRet.getJSONObject("Data");
				JSONObject newData = newRet.getJSONObject("Data");

				T oldBean = getBeanFromJson(oldData, clz, oldTimeFormat);
				if (beanHandlefunction != null) {
					oldBean = beanHandlefunction.apply(oldData, oldBean);
				}

				T newBean = getBeanFromJson(newData, clz, newTimeFormat);

				AssertHelper.assertResultEqual(oldBean, newBean, desc);
			} catch (Exception e) {
				logger.failure(desc,e);
			}
		}));
	}
	
	
	public void startCompare() {
		long useTime = compareThreadPool.runTask(runList);
		System.out.println(useTime);
	}

	public static void main(String args[]) {

	}

}
